﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Reflection;

namespace _5E.Utils.DbHelper
{
    /// <summary>
    /// 程序说明：DataReader帮助类
    /// 创建作者：ahl
    /// 创建时间：2012-03-25
    /// </summary>
    public class DataReaderHelper
    {
        #region 变量

        private DbDataReader m_DataReader = null;

        private readonly static Type[] ARR_BASIC_TYPE = new[] { typeof(string), typeof(char), typeof(Int16), 
            typeof(Int32), typeof(Int64), typeof(Guid), typeof(decimal), typeof(float), typeof(DateTime)};

        #endregion

        #region 静态变量

        private static Func<string, string> s_FormatColumnToProperty = mn => mn;
        public static Func<string, string> FormatColumnToProperty
        {
            set
            {
                if (null == value)
                {
                    throw new ArgumentNullException("列名格式化委托不可空!");
                }
                s_FormatColumnToProperty = value;
            }
        }

        #endregion

        #region 构造函数

        private DataReaderHelper() { }

        public DataReaderHelper(DbDataReader reader)
        {
            m_DataReader = reader;
        }

        #endregion

        #region 实例方法

        public ArrayList ToList()
        {
            var list = new ArrayList();
            using (m_DataReader)
            {
                while (m_DataReader.Read())
                {
                    var count = m_DataReader.FieldCount;
                    var arrValue = new object[count];
                    for (int i = 0; i < count; i++)
                    {
                        var value = m_DataReader[i];
                        arrValue[i] = m_DataReader.IsDBNull(i) ? null : value;
                    }
                    list.Add(arrValue);
                }
            }
            return list;
        }

        public List<T> ToList<T>() where T : new()
        {
            var tList = new List<T>();
            var type = typeof(T);
            Func<T> castMethod = null;
            if (Array.Exists(ARR_BASIC_TYPE, t => t == type))
            {
                castMethod = ToBaseTypeInstance<T>;
            }
            else
            {
                var arrProperty = type.GetProperties();
                castMethod = () => ToClassInstance<T>(arrProperty);
            }
            using (m_DataReader)
            {
                while (m_DataReader.Read())
                {
                    tList.Add(castMethod());
                }
            }
            return tList;
        }

        private T ToBaseTypeInstance<T>()
        {
            var index = 0;
            return m_DataReader.IsDBNull(index) ? default(T) :
                 (T)Convert.ChangeType(m_DataReader.GetValue(index), typeof(T));
        }

        private T ToClassInstance<T>(PropertyInfo[] arrProperty) where T : new()
        {
            var tObj = new T();
            for (int i = 0; i < m_DataReader.FieldCount; i++)
            {
                var name = s_FormatColumnToProperty(m_DataReader.GetName(i));
                if (m_DataReader == null)
                {
                    continue;
                }
                if (Array.Exists(arrProperty, p => p.Name == name))
                {
                    Array.Find(arrProperty, p => p.Name == name).SetValue(tObj, m_DataReader.GetValue(i), null);
                }
            }
            return tObj;
        }

        #endregion
    }
}
